import os
import sys

import bcrypt
from PySide6.QtCore import Qt
from PySide6.QtGui import QIcon, QPixmap
from PySide6.QtSql import QSqlDatabase, QSqlQuery
from PySide6.QtWidgets import (QDialog, QLabel, QLineEdit, QPushButton,
                             QVBoxLayout, QHBoxLayout, QCheckBox, QMessageBox,
                             QFrame, QApplication, QFormLayout)

from patent import PatentApp


class LoginDialog(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("专利导航系统")
        self.setWindowIcon(QIcon('setting/icon.png'))
        self.setFixedSize(600, 600)
        # 关键设置：无边框窗口
        # self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
        self.setStyleSheet("""
            QDialog {
                background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                    stop:0 #2c3e50, stop:1 #3498db);
            /* border-radius: 10px;*/
               /*  border: 2px solid #ffffff;*/  /* 可选：添加白色边框强化圆角效果 */
            }
        """)

        self.init_ui()
        self.ensure_database_exists()

    def ensure_database_exists(self):
        """确保数据库和表存在"""
        db_dir = 'setting'
        os.makedirs(db_dir, exist_ok=True)
        db_path = os.path.abspath(os.path.join(db_dir, 'patents.db'))

        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName(db_path)

        try:
            if not db.open():
                raise ConnectionError("无法连接数据库")

            query = QSqlQuery()
            # 检查表是否存在
            table_exists = query.exec("""
                SELECT name FROM sqlite_master 
                WHERE type='table' AND name='users'
            """)

            if not table_exists or not query.next():
                self.create_user_table(db)

        except Exception as e:
            QMessageBox.critical(self, "数据库错误", f"初始化失败: {str(e)}")
        finally:
            if db.isOpen():
                db.close()
            QSqlDatabase.removeDatabase(db.connectionName())

    def create_user_table(self, db):
        """创建用户表（优化后版本）"""
        query = QSqlQuery(db)
        return query.exec("""
            CREATE TABLE users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT UNIQUE NOT NULL,
                password_hash TEXT NOT NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        """)

    def init_ui(self):
        # 主容器
        main_frame = QFrame(self)
        main_frame.setFixedSize(self.width()-20, self.height()-20)
        # 使用布局管理器使 main_frame 居中
        layout = QVBoxLayout(self)
        layout.addWidget(main_frame, alignment=Qt.AlignmentFlag.AlignCenter)
        # 可选：设置布局的边距（根据需要调整）
        layout.setContentsMargins(10, 10, 10, 10)


        main_frame.setStyleSheet("""
            QFrame {
                background: rgba(255, 255, 255, 0.9);
                border-radius: 10px;
            }
        """)

        # 控件初始化
        # lbl_title = QLabel("专利导航系统", main_frame)
        # lbl_title.setFont(QFont("微软雅黑", 18, QFont.Bold))
        # lbl_title.setStyleSheet("color: #2c3e50;")
        # lbl_title.setAlignment(Qt.AlignCenter)

        # 添加图片（关键代码）
        lbl_image = QLabel(main_frame)
        pixmap = QPixmap("setting/cover.png")  # 替换为实际图片路径
        lbl_image.setPixmap(pixmap.scaled(300, 300, Qt.AspectRatioMode.KeepAspectRatio))  # 缩放图片
        lbl_image.setAlignment(Qt.AlignmentFlag.AlignCenter)  # 图片在 QLabel 中居中

        self.txt_username = QLineEdit(main_frame)
        self.txt_username.setPlaceholderText("请输入账号")
        self.txt_password = QLineEdit(main_frame)
        self.txt_password.setPlaceholderText("请输入密码")
        self.txt_password.setEchoMode(QLineEdit.EchoMode.Password)
        self.chk_show_pwd = QCheckBox("显示密码", main_frame)
        self.chk_show_pwd.stateChanged.connect(self.toggle_password_visibility)

        self.btn_login = QPushButton("立即登录", main_frame)
        self.btn_login.clicked.connect(self.authenticate)
        self.btn_register = QPushButton("添加用户", main_frame)
        self.btn_register.clicked.connect(self.show_registration_dialog)

        # 样式统一
        input_style = """
            QLineEdit {
                border: 2px solid #3498db;
                border-radius: 5px;
                padding: 8px;
                font-size: 14px;
            }
        """
        self.txt_username.setStyleSheet(input_style)
        self.txt_password.setStyleSheet(input_style)

        button_style = """
            QPushButton {
                min-width: 100px;
                padding: 10px;
                border-radius: 5px;
                font-weight: bold;
            }
            QPushButton#login {
                background: #3498db;
                color: white;
            }
            QPushButton#register {
                background: #27ae60;
                color: white;
            }
            QPushButton:hover { opacity: 0.9; }
            QPushButton:pressed { opacity: 0.8; }
        """
        self.btn_login.setObjectName("login")
        self.btn_register.setObjectName("register")
        self.btn_login.setStyleSheet(button_style)
        self.btn_register.setStyleSheet(button_style)

        # 布局管理
        layout = QVBoxLayout(main_frame)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(10)
        # 登录标题
        # layout.addWidget(lbl_title)
        layout.addWidget(lbl_image)
        layout.addWidget(self.txt_username)
        layout.addWidget(self.txt_password)
        layout.addWidget(self.chk_show_pwd)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.btn_login)
        button_layout.addWidget(self.btn_register)
        layout.addLayout(button_layout)
    def show_registration_dialog(self):
        """显示优化后的注册对话框"""
        dialog = QDialog(self)
        dialog.setWindowTitle("添加新用户")
        dialog.setFixedSize(400, 300)  # 增大对话框尺寸

        main_layout = QVBoxLayout(dialog)
        main_layout.setContentsMargins(30, 30, 30, 30)  # 合理边距
        main_layout.setSpacing(20)  # 增加组件间距

        # 使用表单布局排列标签和输入框
        form_layout = QFormLayout()
        form_layout.setVerticalSpacing(15)  # 行间距

        # 用户名输入
        # 将输入框设为对话框的子对象，避免生命周期问题
        reg_username = QLineEdit(dialog)  # 改为局部变量
        reg_password = QLineEdit(dialog)  # 改为局部变量

        reg_username.setPlaceholderText("3-20位字母数字组合")
        reg_username.setMinimumHeight(35)  # 设置最小高度
        reg_username.setStyleSheet("padding: 8px;")  # 增加内边距

        # 密码输入
        reg_password.setPlaceholderText("至少6位字符")
        reg_password.setEchoMode(QLineEdit.EchoMode.Password)
        reg_password.setMinimumHeight(35)
        reg_password.setStyleSheet("padding: 8px;")

        # 添加表单行
        form_layout.addRow(QLabel("用户名:"), reg_username)
        form_layout.addRow(QLabel("密码:"), reg_password)

        # 显示密码复选框
        reg_show_pwd = QCheckBox("显示密码")
        reg_show_pwd.setStyleSheet("QCheckBox { padding: 5px; }")

        reg_show_pwd.stateChanged.connect(
            lambda state: reg_password.setEchoMode(
                QLineEdit.EchoMode.Normal if state else QLineEdit.EchoMode.Password)
        )
        button_style = """
                    QPushButton {
                        min-width: 100px;
                        padding: 10px;
                        border-radius: 5px;
                        font-weight: bold;
                    }
                    QPushButton#cancel {
                        background: #3498db;
                        color: white;
                    }
                    QPushButton#confirm {
                        background: #27ae60;
                        color: white;
                    }
                    QPushButton:hover { opacity: 0.9; }
                    QPushButton:pressed { opacity: 0.8; }
                """


        # 按钮组
        btn_box = QHBoxLayout()
        btn_box.addStretch()  # 添加左侧弹性空间
        btn_confirm = QPushButton("确认")
        btn_confirm.setFixedSize(120, 40)  # 固定按钮尺寸
        btn_confirm.setStyleSheet("QPushButton { font-size: 14px; }")
        btn_confirm.clicked.connect(lambda: self.handle_registration(dialog, reg_username, reg_password))

        btn_cancel = QPushButton("取消")
        btn_cancel.setFixedSize(120, 40)
        btn_cancel.setStyleSheet("QPushButton { font-size: 14px; }")
        btn_cancel.clicked.connect(dialog.reject)

        btn_confirm.setObjectName("confirm")
        btn_cancel.setObjectName("cancel")
        btn_confirm.setStyleSheet(button_style)
        btn_cancel.setStyleSheet(button_style)

        btn_box.addWidget(btn_confirm)
        btn_box.addWidget(btn_cancel)

        # 组装界面组件
        main_layout.addLayout(form_layout)
        main_layout.addWidget(reg_show_pwd)
        main_layout.addStretch()  # 添加弹性空间分隔内容区与按钮
        main_layout.addLayout(btn_box)
        dialog.exec()

    def handle_registration(self, dialog, username_input, password_input):
        """优化的注册逻辑（完整修复版）"""
        username = username_input.text().strip()
        password = password_input.text().strip()

        # 输入验证（增加更详细的检查）
        if not (3 <= len(username) <= 20) or not username.isalnum():
            QMessageBox.warning(self, "输入错误",
                                "用户名需满足：\n• 3-20位长度\n• 只能包含字母和数字")
            return
        if len(password) < 6:
            QMessageBox.warning(self, "输入错误",
                                "密码需满足：\n• 至少6位字符\n• 建议包含字母和数字组合")
            return

        # 数据库连接配置
        db = None
        try:
            # 创建独立数据库连接
            db = QSqlDatabase.addDatabase("QSQLITE", "registration_connection")
            db_path = os.path.abspath(os.path.join('setting', 'patents.db'))
            db.setDatabaseName(db_path)

            if not db.open():
                raise ConnectionError("数据库连接失败")

            # 检查用户名唯一性
            query = QSqlQuery(db)
            query.prepare("SELECT 1 FROM users WHERE username = ?")
            query.addBindValue(username)

            if not query.exec():
                error = query.lastError().text()
                raise RuntimeError(f"用户查询失败: {error}")

            if query.next():
                raise ValueError("该用户名已被注册")

            # 密码加密
            try:
                hashed_pw = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
            except Exception as e:
                raise RuntimeError(f"密码加密失败: {str(e)}")

            # 插入新用户
            query.prepare("""
                INSERT INTO users (username, password_hash)
                VALUES (?, ?)
            """)
            query.addBindValue(username)
            query.addBindValue(hashed_pw.decode())

            if not query.exec():
                error = query.lastError().text()
                raise RuntimeError(f"用户创建失败: {error}")

            QMessageBox.information(dialog, "成功", "用户注册成功！")
            dialog.accept()

        except Exception as e:
            QMessageBox.critical(dialog, "注册失败",
                                 f"操作未能完成：\n{str(e)}")
        finally:
            # 确保关闭数据库连接
            if db and db.isOpen():
                db.close()
            if db:
                QSqlDatabase.removeDatabase("registration_connection")

    def authenticate(self):
        """优化的登录验证逻辑"""
        username = self.txt_username.text().strip()
        password = self.txt_password.text().strip()

        if not username or not password:
            QMessageBox.warning(self, "输入错误", "用户名和密码不能为空！")
            return

        db_path = os.path.abspath(os.path.join('setting', 'patents.db'))
        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName(db_path)

        try:
            if not db.open():
                raise ConnectionError("无法连接数据库")

            query = QSqlQuery(db)
            query.prepare("""
                SELECT password_hash 
                FROM users 
                WHERE username = ?
                LIMIT 1
            """)
            query.addBindValue(username)

            if not query.exec():
                raise RuntimeError(f"查询失败: {query.lastError().text()}")

            if not query.next():
                raise ValueError("用户不存在")

            stored_hash = query.value(0).encode('utf-8')

            if not bcrypt.checkpw(password.encode('utf-8'), stored_hash):
                raise ValueError("密码错误")

            self.accept()

        except Exception as e:
            error_messages = {
                "用户不存在": "用户名不存在",
                "密码错误": "密码不正确",
                "无法连接数据库": "数据库连接失败"
            }
            QMessageBox.critical(
                self,
                "登录失败",
                error_messages.get(str(e), f"未知错误: {str(e)}"))
            self.txt_password.clear()
        finally:
            if db.isOpen():
                db.close()
            QSqlDatabase.removeDatabase(db.connectionName())

    def toggle_password_visibility(self, state):
        """切换密码显示状态"""
        self.txt_password.setEchoMode(
            QLineEdit.EchoMode.Normal if state else QLineEdit.EchoMode.Password)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 先显示登录窗口
    login_dialog = LoginDialog()
    if login_dialog.exec() != QDialog.DialogCode.Accepted:
        sys.exit(0)  # 登录失败退出程序
    window = PatentApp()
    window.show()
    sys.exit(app.exec())
